perm filename JUST[E,ALS]3 blob sn#219263 filedate 1976-06-17 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00005 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	MINTXT TABCNT TABTAB JPARAM JGINIT JGB JGIND JGMAR JGET TJGET
C00019 00003	JCTAB
C00033 00004	JSET JUST
C00045 00005	INDENT INDMAR CENTER
C00050 ENDMK
C⊗;
;MINTXT TABCNT TABTAB JPARAM JGINIT JGB JGIND JGMAR JGET TJGET

MINTXT←←3			;Minimum allowed text length or TAB field
TJSCNT←←2			;Minimum number of spaces to terminate a TAB field
TABCNT←←50			;Allow 40 tabs

IMPURE

PMARO:	0
LMARO:	0

JPMARO:	0
JLMARO:	0
JPMAR:	0
JLMAR:	0
JRMAR:	69
JBNUM:	1
JBNUMO:	1

TPMARO:	0
TLMARO:	0
TPMAR:	0
TLMAR:	0
TRMAR:	69
TBNUM:	1
TBNOMO:	1

TABTAB:	BLOCK	TABCNT

PURE
;  Subroutine to read typed-in decimal numbers.
;Returns the number in A, the terminating character in C and
;a count of the number of digits in B.
JPARAM:	SETZB A,B
	SETZ C,
JPAR0:	PUSHJ P,TYI		;Get first character if any
	POPJ P,
	CAIN C," "
	JRST JPAR0		;Extra space allowed here
	AOS (P)			;Skip return if something typed
	JRST JPAR2
JPAR1:	PUSHJ P,TYI		;Get next character
	POPJ P,			;End of typing
JPAR2:	CAIG C,71
    	CAIGE C,60
	POPJ P,			;Non numeric character
	IMULI A,12
	ADDI A,-"0"(C)
	AOJA B,JPAR1		;B used to indicate some number (may be zero)

;  Subroutine called by JGET and TJGET
;to clear PAR table and to read and store typed-in MAR values.
JGINIT:	TRNN F,ARG
	HRRZI A,-1		;Use rest of page (or buffer) if no argument
	MOVMM A,JCNT
	JUMPE A,JGIN1		;No text referencing
	MOVE T,EXTPNT		;To read JPARAM changing instructions.
	MOVEM T,TYIPNT		;Set pointer.
	HRLI C,(<MOVEI C,>)
	MOVEM C,TYIINS
	MOVSI Q,-4
	SKIPN JCNT
	JRST JGIN1	 	;Leave old values if JCNT=0 and no typed value
	SETOM JPMAR(Q)
	AOBJN Q,.-1
	TRNE F,ATTMOD		;Are we in ATTACH mode?
	SKIPA E,[JATAB]		;   Yes so put [JATAB] in E.
	MOVEI E,JPTAB		;   No so put [JPTAB] in E.
	MOVE D,@JPT1(E)		;Put contents of @ATTBUF or @ARRLIN in D.
	HRRZM D,JPTR#		;Location of first line to examine
	MOVE A,JLPTR(E)		;Number of lines
	TRNE F,ATTMOD
	JRST JGIN0
	SUB A,ARRL
	ADDI A,1
JGIN0:	CAMGE A,JCNT
	MOVEM A,JCNT		;Limit number of lines to the available ones
	MOVN G,JCNT
	HRLZS G
	MOVEM G,GSAVE#		;May be needed again later
	MOVSI Q,-4
	PUSHJ P,JPARAM		;Read first parameter
	POPJ P,			;Nothing typed
	CAME C,"|"		;Was a "|" separater used, meanind JPMARO (old)
	JRST JGIN2		;No
	MOVEM A,JPMARO
JGIN1:	PUSHJ P,JPARAM		;Read a parameter
	POPJ P,			;Nothing typed
JGIN2:	JUMPE B,JGIN3		;B=0 means no number before symbol
	MOVEM A,JPMAR(Q)
	SOS Q			;Q-right left with count of unspecified fields
JGIN3:	CAIN C,","		;Any other symbol terminates JGINIT
	AOBJN Q,JGIN1
	POPJ P,

;  Subroutine called by JGMAR
;Will locate the first non-blank line after 1 or  more blank lines and
;return the number of blank lines in B (B set to 0 before entry).
;Pointer to the first line of text in D and the specification of the number
;of lines of text (as a negative number) in the left of G.
JGB0:	HRRZ D,(D)
JGB:	HRRZ C,TXTCNT(D)
	JUMPN C,JGB1
	AOJA B,JGB2		;Count blank lines for JBNUM
JGB1:	CAMLE C,Q
	MOVE Q,C		;Put largest in Q for JRMAR
	JUMPE B,JGB2
	MOVEM B,JBNUMO		;Save it here always
	SKIPGE JBNUM		;Was a JBNUM typed in?
	MOVEM B,JBNUM		;No, so use this value
	MOVEM G,GSAVE		;May be needed twice
	MOVEM D,JPTR		;Save new starting place in text
	JRST JGB1B

JGB1A:	HRRZ D,(D)		;Go to end for Q determination
	HRRZ C,TXTCNT(D)
	CAMLE C,Q
	MOVE Q,C
JGB1B:	AOBJN G,JGB1B		;Are we at the end?
	MOVE G,GSAVE		;Reset for first line after blanks
	MOVE D,JPTR
	POPJ P,			;Text found after a blank line

JGB2:	AOBJN G,JGB0		;Still looking
	MOVE D,JPTR		;No text found after blank line, so reset
	MOVE G,GSAVE
	SETZ B,			;Blank lines without text following, do not count
	MOVEM B,JBNUMO		;Save it here always
	SKIPGE JBNUM		;Was a JBNUM typed in?
	MOVEM B,JBNUM		;No, so use this value
	PUSHJ P,JGIND		;Get first line indent
	HRRZ TT,T		;Save it
JGB3:	AOBJP G,JGB4
	HRRZ D,(D)		;Try the next line
	PUSHJ P,JGIND
	CAIN TT,(T)
	AOJA B,JGB3		;Another line with the same indent
	JUMPE B,JGB4		;More than 1 line with same indent?
	MOVEM G,GSAVE
	MOVEM D,JPTR
	POPJ P,

JGB4:	MOVE G,GSAVE		;Go back to first line if B still zero
	MOVE D,JPTR
	POPJ P,

;To get indentation
JGIND:	HRRZ T,TXTCNT(D)
	MOVNS T
	HRLZS T
	MOVE A,D
	ADD A,[440700,,LLDESC]
JGIND1:	ILDB C,A
	CAIN C,11		;Is it a TAB?
	JRST JGIND1		;Ignore it
	CAIN C," "		;Is it a space?
	AOBJN T,JGIND1		;Count it
	POPJ P,

;   Subroutine called by JGET and TJGET
;To determine margins from specified text
JGMAR:	MOVN G,JCNT
	HRLZS G
	MOVEM G,GSAVE		;May be needed twice
	SETZB B,Q		;B counts blank lines, Q gets JRMAR
	MOVE D,JPTR		;Pointer to the first line of text
	PUSHJ P,JGB		;Find paragraph start
	PUSHJ P,JGIND		;Get its indentation
	MOVEM T,INDCNT#		;May be needed for TJGET case
	MOVEM A,ASAVE#		;and also pointer to first non-blank character
	HRRZM T,JPMARO		;Save it always
	SKIPGE JPMAR		;Was a new value typed?
	HRRZM T,JPMAR		;No, so use this value
	AOBJN G,JGM0		;Trouble, not enough lines
	SETZM JBNUMO		;Maybe he wants 1 paragraph
	JRST JGMA
JGM0:	HRRZ D,(D)
	PUSHJ P,JGIND		;Get indentation of the next line
JGMA:	HRRZM T,JLMARO
	SKIPGE JLMAR		;Was a new value typed?
	HRRZM T,JLMAR		;No, so save this value
	SKIPG JRMAR		;Was a new JRMAR typed in?
	MOVEM Q,JRMAR		;No, so save this value
	POPJ P,

;To test margins for legality
JMTEST:	MOVE A,JPMAR
	CAME A,JLMAR
	JRST JMTES1
	SKIPLE JBNUM
	JRST JMTES1
	MOVEI T,1
	MOVEM T,JBNUM		;Must be ≥1 in this case
	OUTSTR [ASCIZ/BNUM set to 1./]
JMTES1:	CAMG A,JLMAR
	MOVE A,JLMAR
	ADDI A,MINTXT		;Minimum text length
	CAMG A,JRMAR
	POPJ P,
	MOVEM A,JRMAR
	OUTSTR [ASCIZ/ RMAR set to /]
	TYPDEC A
	OUTSTR [ASCIZ/ /]
	POPJ P,

;Get typed-in margins and/or values identified from the specified text.
JGET:	JUMPN A,JGET2
	MOVSI Q,-4
JGET1:	MOVE T,PMAR(Q)
	MOVEM T,JPMAR(Q)
	AOBJN Q,JGET1
JGET2:	PUSHJ P,JGINIT		;Initialize and get typed-in margin values
	CAIN C,";"		;To avoid confusion with TJGET
	OUTSTR [ASCIZ/Caution, no TAB values allowed with JGET command./]
	SKIPE JCNT
	PUSHJ P,JGMAR		;Get margins by examining the text
	OUTSTR [ASCIZ/Margins (P,L,R,B) are /]
	SKIPE JBNUMO		;Were there no blank lines in text?
	JRST JGET2A
	MOVE A,JPMARO
	CAMN A,JPMAR		;Is PMAR being changed?
	JRST JGET2A
	TYPDEC A		;Report it
	OUTSTR [ASCIZ/|/]
JGET2A:	MOVSI G,-4
	SETZM TYOPNT
	SKIPA
JGET3:	OUTSTR [ASCIZ/,/]
	MOVE A,JPMAR(G)
	MOVEM A,PMARS(G)
	TYPDEC A
	AOBJN G,JGET3
	OUTSTR [ASCIZ/. /]
	AOS (P)
	POPJ P,
	
;Get margins and also TAB settings
TJGET:	JUMPN A,TJGB
	MOVSI Q,-4
TJGA:	MOVE T,TPMAR(Q)
	MOVEM T,JPMAR(Q)
	AOBJN Q,TJGA
TJGB:	PUSHJ P,JGINIT		;Initialize and get typed margin values
	MOVSI Q,-TABCNT
	SKIPG JCNT
	JRST TJG1
	SETZM TABTAB(Q)		;Set TABTAB to 0 if JCNT>0
	AOBJN Q,.-1
TJG1:	CAIE C,";"
	CAIN C,"!"
	SKIPA
	JRST TJG7		;No typed TAB values
	SKIPLE JCNT
	JRST TJG2
	HLLZS TABTAB(Q)		;Zero indent values only
	AOBJN Q,.-1
TJG2:	MOVSI Q,-TABCNT
	CAIN "!"
	JRST TJG4A		;Next number is to be an indent not a field size
TJG3:	PUSHJ P,JPARAM
	JRST TJG7		;A ; typed but no data
	CAIE C,"@"		;Is this a multiple define
	JRST TJG5
	MOVE H,A		;Yes, so save repetition number in H
	PUSHJ P,JPARAM		;and get field size
	JRST TJG7		;No data means leave rest unchanged
TJG4:	SKIPE A			;A zero or missing value means leave unchanged
	HRLZM A,TABTAB(Q)
	AOBJP Q,TJG7A		;No more space so ignore the rest
	SOJG H,TJG4
	JRST TJG6		;See if there are any more

TJG4A:	PUSHJ P,JPARAM		;Get indent value
	SKIPA			;Syntax error
	JUMPG A,TJG4B		;An indent can not be zero
	OUTSTR [ASCIZ/IMPROPER SYNTAX, a non-zero number must follow a "!" symbol/]
	POPJ P,
TJG4B:	HRRZM A,TABTAB(Q)
	AOBJP Q,TJG7A
	JRST TJG6

TJG5:	JUMPE B,TJG6		;Was a number typed?
	HRLZM A,TABTAB(Q)	;Yes, so save it as a field length
TJG6:	CAIN C,","
	JRST TJG3
	CAIN C,"!"
	JRST TJG4A
	SKIPA
TJG7A:	OUTSTR [ASCIZ/ Too many TABs typed, will ignore rest. /]
TJG7:	SKIPN JCNT		;Are values to be deduced from the text?
	JRST TJG18		;No
	PUSHJ P,JGMAR		;Get margins from the text
	MOVSI Q,-TABCNT
	MOVE A,ASAVE		;Get back to the first non-space char in 1st line
	MOVE G,INDCNT		;Get character counter for first non-space
TJG8B:	SETZ T,
TJG8C:	SETZ H,
TJG8:	AOS T			;We start on the first char
	ILDB C,A
	CAIE C," "
	CAIN C,11
	JRST TJG11		
TJG8A:	AOBJN G,TJG8
	JRST TJG15

;To count spaces or TABS to check field termination
TJG9A:	AOS H
TJG9:	AOS T
TJG10:	ILDB C,A		;A space or TAB found, is there another one?
TJG11:	CAIE C," "		;Is it a space?
	JRST TJG12
	AOBJN G,TJG9A
	JRST TJG15

TJG12:	CAIN C,11		;or a TAB?
	AOJA H,TJG10		;TABs do not count in G or T, but add to H
	CAIL H,TJSCNT		;Were there JSCNT or more spaces?
	JRST TJG13		;Yes, so at end of this TAB field
	AOBJN G,TJG8C		;Single spaces allowed within fields
	JRST TJG15

TJG13A:	OUTSTR [ASCIZ/ Only /]
	MOVEI A,TABCNT
	TYPDEC A
	OUTSTR [ASCIZ/ TABS allowed. /]
	JRST TJG15

TJG13:	SKIPG TABTAB(Q)		;Has this TAB been typed in?
	HRLZM T,TABTAB(Q)	;Save field length
	AOBJP Q,TJG13A
	AOBJN G,TJG8B
TJG15:	MOVSI Q,-TABCNT
	MOVE TT,JPMAR
TJG16:	SKIPG TABTAB(Q)
	JRST TJG18		;No more values specified
	HLRZ T,TABTAB(Q)
	JUMPG T,TJG17B		;A field length was specified
TJG17:	HRRZ T,TABTAB(Q)	;An indent was specified
	SUB T,TT
	CAIL T,MINTXT
	JRST TJG17A		;Field would be too small
	OUTSTR [ASCIZ/ TAB field #/]
	HRRZ C,Q
	TYPDEC C
	OUTSTR [ASCIZ/ set at min. length of /]
	MOVEI T,MINTXT
	TYPDEC T
	OUTSTR [ASCIZ/. /]
TJG17A:	HRLM T,TABTAB(Q)
TJG17B:	ADD TT,T
	HRRM TT,TABTAB(Q)	;May have been corrected
	AOBJN Q,TJG16
	JRST TJG18

TJG18:	OUTSTR [ASCIZ/Margins P,L,R,B) are /]
	SETZM TYOPNT
	MOVSI Q,-4		;Report values
	SKIPA
TJG19:	OUTSTR [ASCIZ /,/]
	MOVE T,JPMAR(Q)
	MOVEM T,TPMAR(Q)
	TYPDEC T
	AOBJN Q,TJG19
	OUTSTR [ASCIZ/. /]
	SKIPG TABTAB		;Are there any TABS?
	JRST TJG23
	OUTSTR [ASCIZ/
TAB fields /]
	MOVSI Q,-TABCNT
	SKIPA
TJG20:	OUTSTR [ASCIZ/,/]
	SETZ H,
	HLRZ T,TABTAB(Q)
TJG20A:	HLRZ TT,TABTAB+1(Q)
	CAME T,TT
	JRST TJG20B
	AOS H
	AOBJN Q,TJG20A
	
TJG20B:	JUMPE H,TJG20C
	AOS H			;The first one was not counted
	TYPDEC H		;Count of similar fields
	OUTSTR [ASCIZ/@/]
TJG20C:	TYPDEC T
	SKIPLE TABTAB+1(Q)
	AOBJN Q,TJG20
TJG21:	OUTSTR [ASCIZ/  starting at /]
	MOVE T,JPMAR
	ADDI T,1
	TYPDEC T
	MOVSI Q,-TABCNT
TJG22:	OUTSTR [ASCIZ/,/]
	HRRZ T,TABTAB(Q)
	ADDI T,1
	TYPDEC T
	SKIPLE TABTAB+1(Q)
	AOBJN Q,TJG22
	OUTSTR [ASCIZ/. /]
	AOS (P)
	POPJ P,

TJG23:	OUTSTR [ASCIZ/ No TABs specified./]
	POPJ P,
;JCTAB

COMMENT ⊗
Register assignments used in main section of JUST (and related routines)

	A	Input character pointer
	B	Input line address
	C	Current character
	D	Output character pointer
	E	Address of table defining data region
	F	Usual flag word
	G	Character count for output line (-x,,0 at start)
	H	Special flag word
	I	Address of line into which characters are going
	DSP	Current dispatch table address
	P	Stack pointer, as usual
	Q	Temporary
	T	Temporary
	TT	Temporary
Special flag usage with F during JUST only (after initial normal usage)
	NEG	set to 0 for JUST, to 1 for JFILL
	REL	set to 0 for no par. break, to 1 for par. break
End of comment ⊗

;Special flags tested against H (for use with JUST and related commands)

	JUSF←←200000	;CR, LF, VT, FF, SP, TAB, . ! ?
;	LSPC←←100000	;Special character, previously defined
;	NUMF←←40000	;Number			"	"
	JALL←←20000	;Dispatch on all characters
;	LETF←←10000	;Letter	(with LT2F => lower case)
;	LT2F←←4000	;Alone=> $ % . _
	JPUN←←2000	;Sentence-ending punctuation
	JCLO←←1000	;Closing parenthesis

;Dispatch displacements used in following table

;	0	CR, LF and all chars. not allowed in in-core page representation
;	1	TAB (11)
;	2	Space (40)
;	3	Sentence terminating punctuation . ? !
;	4	Closures ) ] > } "
;	5	All other normal characters

;Special character-dispatch table for use with JUST and related commands

JCTAB:	JALL!JUSF,,(DSP)		;NUL	0
	REPEAT 8<JALL,,5(DSP)>		;↓ α β ∧ ¬ ε π λ   1,2,3,4,5,6,7,10

	JALL!JUSF!LSPC,,1(DSP)		;TAB	11
 	REPEAT 3,<JALL!JUSF!LSPC,,(DSP)>  ;LF,VT,FF	12,13,14
	JALL!JUSF!LSPC,,(DSP)		;CR	15
	JALL,,5(DSP)			;∞	16
	JALL,,5(DSP)			;∂	17

	REPEAT 16,<JALL..5(DSP)>   ; ⊂ ⊃ ∩ ∪ ∀ ∃ ⊗ ↔ _ → ~ ≠ ≤ ≥ ≡ ∨  20 thru 37

	JALL!JUSF,,2(DSP)		;SP	40
	JALL!JUSF!JPUN,,3(DSP)		;!	41
	JALL!JCLO,,4(DSP)		;"	42
	REPEAT 5,<JALL,,5(DSP)>		;# % & '	43,44,45,46,47

	JALL!,,5(DSP)			;(	50
	JALL!JCLO,,4(DSP)		;)	51
	REPEAT 4,<JALL,,5(DSP)>		;* + , -	52,53,54,55
	JALL!JUSF!JPUN,,3(DSP)		;.	56
	JALL,,5(DSP)			;/	57

	REPEAT 10,<JALL!NUMF,,5(DSP)>	;0,1,2,3,4,5,6,7,8,9	60 thru 71
	REPEAT 2,<JALL!JPUN,,5(DSP)>	; : ;	72,73
	REPEAT 2,<JALL,,5(DSP)>		; < =	74,75
	JALL!JCLO,,4(DSP)		; >	76
	JALL!JUSF!JPUN,,3(DSP)		;?	77

	JALL,,5(DSP)			;@	100
	REPEAT 26,<JALL!LETF,,5(DSP)>	;A to Z	101 thru 132
	REPEAT 2,<JALL,,5(DSP)>		;[ \	133,134
	JALL!JCLO,,4(DSP)		;]	135
	REPEAT 3,<JALL,,5(DSP)>		;↑ ← `	136,137,140

	REPEAT 26,<JALL!LETF!LT2F!,,5(DSP)>  ;a th z	 141 thru 172
	JALL,,5(DSP)			;{	173
	JALL,,5(DSP)			;|	174
	JALL!JUSF!LSPC,,(DSP)		;ALT	175
	JALL!JCLO,,4(DSP)		;}	176
	JALL!JUSF!NSPEC,,(DSP)		;RUBOUT	177


	IMPURE

;Memory locations to hold other variables
JCNT:	0	Count of lines to be processed
JCNTC:	0	Current value of JCNT
JPTR:	0	Location of first line of text being processed
JPTRC:	0	;Location of first line of group currently being handled
JRPT:	0	Next line after text being processed
JWCOL:	0	Char count at last word break
JSCNT:	0	Word break count
JBUGR:	0	Bugger factor to distribute extra spaces
JWPT:	0	Accumulated count of extra spaces added
JSINC:	0	Needed spaces times 8
JSIZE:	0	JSINC times number of breaks already processed
JMARG:	0	;Current output line's left margin
PARFLG:	0	;Set for new par. conditions as defined by PMARO, LMARO and BNUMO
;	Value assigned to PARFLG
;	0	means blank line needed to signal new par.
;	-1	means new par. every new line
;	+1	means new par if indent is >1
;	X>1	means new par. if indent is =X

	PURE


;  Routine for setting up correct value for PARFLG

PARSET:	SETZM PARFLG		;Used if blank line needed to signal new par.
	MOVE T,PMARO
	CAME T,LMARO
	JRST PARSE2		;Test some more
	SKIPN BNUMO
	SETOM PARFLG		;Every old line a new par. in this case
	POPJ P,

PARSE2:	AOS PARFLG		;Prepare to accept any >1 indent
	SKIPE BNUMO		;if BNUMO=0
	MOVEM T,PARFLG		;Requires indent=PARO if BNUMO≠0
	POPJ P,

;   Subroutine to get new par. indicator
P1NXTL:
PARGET:	TRZ F,REL		;Means no new par.
	HRRZ B,(B)
	MOVE A,B
	ADD A,[440700,,LLDESC]
	MOVE T,TXTCNT(B)
	JUMPE T,PARGE2		;A blank line
	SKIPN TT,PARFLG		;Test conditions
	POPJ P,			;No par indicated
	JUMPL TT,PARGE2		;Always a new par.
	MOVE T,A		;We will have to test new line indent
	SETZ TT,
PARGE1:	ILDB C,T
	CAIN C,11
	JRST PARGE1
	CAIN C,40
	AOJA TT,PARGE1
	CAMN TT,PARFLG		;Is indent equal to PMARO
	JRST PARGE2		;Yes, so a new par.
	MOVE T,PARFLG
	CAIN T,1		;Will a >1 indent suffice?
	CAIG TT,1		;Is indent greater than 1?
	POPJ P,			;No
PARGE2:	TRO F,REL		;New paragraph signal
	POPJ P,



;  For second pass when input line is exhausted
NEXTLI:
	HLRZ T,TXTCNT(B)
	MOVNI T,(T)			;and do 1's complement of T
	ADDM T,@JCPTR(E)		;add this to # in CHARS or ATTSIZ.
	SOS @JLPTR(E)			;Subtract 1 from # in LINES or ATTNUM.
	HRRZ B,(B)			;Get line forward pointer
	MOVEM B,JPTR			;and put it in JPTR.
	MOVSI T,JPTR			;with JPTR location in left half
	HLLM T,(B)			;of pointer for line pointed to.
	PUSHJ P,FSGIVE			;Give up storage space.
	MOVE A,B
	ADD A,[440700,,LLDESC]
	POPJ P,

;  Action on reaching a CR in the input text
JUSTCR:
	SKIPN JPASSF		;Is this the first pass
	JRST JUSTC3		;Yes
	PUSHJ P,NEXTLI		;Finish off line and get next
	SOSG JCNT
	JRST JUSTC5		;We should never get here, but just in case
JUSTC1:	MOVEI C,40
	SOS (P)			;To interpret the CR
	POPJ P,

;  First pass treatment
JUSTC3:	SOSG JCNTC
	JRST JUSTC4		;Treat end of text as end of par. here
	PUSHJ P,PARGET		;To get correct par info.
	TRNN F,REL
	JRST JUSTC1		;No new par. so replace CR with space and continue
JUSTC4:	TRO F,REL		;May enter here if end of data
	CAIN DSP,J1DSP		;Save data only after a non-space last char.
	JRST JUSTC5
	AOS JSCNT		;Add to word break count
	HRRZM G,JWCOL		;Char count at this word break
JUSTC5:	AOS (P)			;Forces an exit from loop without incrementing G
	POPJ P,

;  To introduce extra spaces as required to justify
JUSPAD:	SKIPN T,JSINC		;8 times the needed number of extra spaces
	POPJ P,			;Exit if no extra spaces are required
	ADDB T,JWSIZE
	IDIV T,JSCNT		;Divide by available-location count
	ADD T,JBUGR		;Current bugger factor to distribute extra spaces
	LSH T,-3		;Divide by 8
	SUB T,JWPT		;JWPT counts additions to date
	ADDM T,JWPT
	JUMPE T,JUSPA2
JUSPA1:	IDPB C,D		;Add an extra space
	AOBJP G,JUSPA2		;Should always be negative
	SOJG T,JUSPA1
JUSPA2:	POPJ P,


;   To eat all extra spaces and tabs
J1SP:	MOVE C,[-3]
	ADDM C,(P)		;This backs up to the ILDB command
	POPJ P,

;  Action at end of a word signalled by a space or tab
J2TAB:	MOVEI C,40
J2SP:	MOVEI DSP,J1DSP
	MOVSI H,JALL
	SKIPE JPASSF	;Test for pass
	JRST J2SP2	;Second pass
	AOS JSCNT	;Add to word break count
	HRRZM G,JWCOL	;Char count to this word break
	POPJ P,

J2SP2:	TRNN F,NEG!REL	;Is this line to be justified?
	PUSHJ P,JUSPAD	;Introduce extra spaces as needed
	POPJ P,

;  Action on receipt of a sentence-terminating type punctuation mark
J2PUN:	MOVEI DSP,J3DSP
	MOVSI H,JALL
	POPJ P,

;  Action at end of sentence signalled by punctuation and space or tab
J3TAB:	MOVEI C,40
J3SP:	MOVEI DSP,J1DSP
	SKIPE JPASSF
	JRST J3SP2	;Its on the second pass
	AOS JSCNT	;Add to word break count
	HRRZM G,JWCOL	;Char count at this word break
	AOBJN G,J3SP1	;Count for an extra space if possible
	SUB G,[1,,1]
J3SP1:	POPJ P,

J3SP2:	IDPB C,D	;Introduce second space always
	AOBJN G,J2SP2	;(should always be OK)
	POPJ P,		;Safety exit

;  Action on normal character if using JIDSP or J3DSP
JCHAR:	MOVEI DSP,J2DSP
	MOVSI H,JUSTF
	POPJ P,

;Special dispatch tables used with JCTAB (Table address in DSP)
; and using the above routines
;  After a space with JALL flag used
J1DSP:	PUSHJ P,JUSTCR	;CR
	PUSHJ P,J1SP	;TAB	(eaten)
	PUSHJ P,J1SP	;Space  (eaten)
	PUSHJ P,JCHAR	;Punctuation	(MOVEI DSP,J2DSP↔MOVSI H,JUSTF)
	PUSHJ P,JCHAR	;Closure      		"		"    
	PUSHJ P,JCHAR	;Other character	"		"

;  After a normal char. with JUSTF flag used
J2DSP:	PUSHJ P,JUSTCR	;CR
	PUSHJ P,J2TAB	;TAB		(MOVEI DSP,J1DSP↔MOVSI H,JALL)
	PUSHJ P,J2SP	;Space			"		"
	PUSHJ P,J2PUN	;Punctuation	(MOVEI DSP,J3DSP↔MOVSI H,JALL)
	JFCL		;(Never used)
	JFCL		;(Never used)

;  After sentence-terminating puncuation with JALL flag used
J3DSP:	PUSHJ P,JUSTCR	;CR
	PUSHJ P,J3TAB	;TAB	(Replaced by space and handled as such)
	PUSHJ P,J3SP	;Space	(Introduces extra space and MOVEI DSP,J1DSP)
	JFCL		;Punctuation
	JFCL		;Closure
	PUSHJ P,JCHAR	;Other character  (MOVEI DSP,J2DSP↔MOVSI H,JUSTF)

;JSET JUST

;  Get space for first new line
JNEW:	PUSHJ P,ENDSET		;So new lines will be at the end of FS
	TLO F,NOCHK		;Don't CORE DOWN untill through
	HRRZ Q,(B)
	MOVEM Q,JRPT#		;Keep current next line address
	CAMN B,PAGE
	TRO F,UPDTXT		;This is the first line on the page
	HLLZ Q,TXTFLG(B)	;Save flags
	HRRZ I,FSEND
	ADDI I,1
	MOVEM I,JLPT
	HLLZ TT,(B)		;Use the left half of old link for
LEG	MOVEM TT,(I)		;left half of the new link word, zero right
	HLRZ T,TT
 	HRRM I,(T)		;Fix earlier forward link to the new line
LEG	HLLM Q,TXTFLG(I)	;Use old flags
	TLNI Q,ARRBIT		;May need to reset ARRLIN
	MOVEM I,ARRLIN
	TLNE Q,WINBIT		;and also WINLIN
	MOVEM I,WINLIN
	SETZ Q,
	POPJ P,

;  Get space for next output line
JMORE:	HRRZ TT,FSEND		;So get space starting address
	ADDI TT,1
	HRRM TT,I
LEG	HRLM I,(TT)
	MOVEM TT,JLPT
	MOVE I,JLPT
	POPJ P,

;Introduce CRLF and finish off the line
JUFIX:	MOVEI C,15
LEG	IDPB C,D		;The CR
	MOVEI C,12
LEG	IDPB C,D		;And a LF
	TDZA C,C
LEG	IDPB C,D		;And a null
	TLNE D,760000
	JRST .-2
	ADDI TT,2(G)		;2 for CRLF + char. count
	HRLZS TT		;goes into left half
	ADDI TT,(G)		;but only char. count into right half
	ADDM TT,TXTCNT(I)	;Record char counts
	MOVE T,JLPT		;should be same as I
;Display text must be in ASCID
	ADDI T,LLDESC		;Get address of first text word
	MOVEI TT,1
	IORM TT,(T)		;Convert to ASCID
	CAIGE T,(D)
	AOJA T,.-2
	MOVEI TT,2(D)
	MOVSI T,TXTCOD
	FSFIX TT,T
	POPJ P,

;   Prepare for the second pass
J2PASS:	SETOM JPASSF		;Set for second pass
	MOVEI DSP,J1DSP		;Always eat initial spaces
	MOVSI H,JALL
	AOS TT,TXTNUM
LEG	HRRM TT,TXTSER(I)	;Assign I new serial number
	MOVE D,I		;Set up output char pointer
	ADD D,[440700,,LDESC]
	MOVE T,JMARG		;Get correct current margin value
	IDIVI T,10		;See if TABs are to be used
LEG	HRLZM T,TXTCNT(I)	;Start new TXTCNT (with credit for any TABs)
	JUMPE T,J2PAS3		;No TABs
	MOVEI C,11
J2PAS0:
LEG	IDPB C,D
	MOVEI C,40
	MOVEI Q,10		;Temporary use only
	ADDM Q,TXTCNT(I)	;Count as displayed chars. only
J2PAS1:
LEG 	IDPB C,D
	SOJG Q,J2PAS1
	MOVEI C,11
J2PAS2:
LEG	IDPB C,D
	SOJG T,J2PAS0
J2PAS3:	JUMPE TT,J2PAS5		;No extra spaces in JMARG
	HRR T,TT
	HRL T,TT
	ADDM T,TXTCNT(I)	;Count both as stored and as displayed
	MOVEI C,40
J2PAS4:
LEG	IDPB C,D
	SOJG TT,J2PAS4
J2PAS5:	MOVE A,ASAVE
	MOVE B,JPTR
	MOVE C,JCNT
	MOVEM C,JCNTC
	POPJ P,

JFILL:	TRO F,NEG		;For JFILL case
JUST:	TRZ F,NEG		;For JUST case
	TRNE F,ARG!ATTMOD
	JRST JU1
	PUSHJ P,SETARR		;JUST without an argument does entire page
	MOVEI A,-1
JU1:	PUSHJ P,JGINIT		;Initialize and get typed-in margins
	PUSHJ P, PARSET		;Set up new par. requirements
	MOVSI H,JALL		;Set to dispatch on all characters
	MOVEI DSP,J1DSP		;Set dispatch for new output line
	MOVE B,JPTR
	TRZ F,REL		;Means not new par. on first pass
	SETZM JBUGR		;Bugger factor that staggers inserted spaces
JU1A:	HRRZ C,TXTCNT(B)	;Is this line blank?
	JUMPN C,JU1B		;No
	HRRZ B,(B)		;Skip over it
	MOVEM B,JPTR		;Initial blank lines are left but signal new par
	SOSG JCNT		;One less line to process
	POPJ P,			;No data
	TRO F,REL		;Means new par. indent to start
	JRST JU1A

JUIB:	PUSHJ P,JNEW		;Get space for new lines and fix flags etc.
	MOVE A,B
	ADD A,[440700,,LLDESC]
	TRNN F,REL		;Alrready know that new par. indent is to be used
JU1C:	PUSHJ P,PARGET
JU1D:	MOVE G,LMAR
	TRNE F,REL		;No new par indent if 0
	MOVE G,PMAR
	MOVEM G,JMARG		;Save as current margin for second pass
	SUB G,RMAR
	MOVNM G,JSIZE		;The expected size of new line less margin
	SUBI G,1		;Go 1 char. beyond on the first pass
	HRLZS G
	MOVEM A,ASAVE
	SETZM JSCNT		;To count word separators
	MOVE C,JCNT
	MOVEM C,JCNTC
	MOVEI DSP,J1DSP		;Always eat initial spaces
	MOVSI H,JALL
;First pass
;   Determine accepted-char. count, # of word separators and par. conditions
JU3:	ILDB C,A
	TDNE H,JCTAB(C)
	XCT @JCTAB(C)		;Caution, return may be .-2, ., .+1 or .+2
	AOBJN G,JU3
	SKIPN JSCNT		;Have we come to a word break?
	JRST JU3		;Impossible to break line so go on
	SETZM JSINC		;Safety precaution only
;  Verify par. conditions
	LDB C,A			;GET last char. back
	CAIN C,15		;Was it a CR?
	JRST JU3B		;YES, so no further testing needed
	SKIPA
JU3A:	ILDB C,A
	CAIE C,40
	CAIN C,11
	JRST JU3A		;Eat all spaces and TABs
	CAIE C,15		;Now do we find a CR?
	JRST JU3B		;No, so some text is left
	PUSHJ P,PARGET		;Yes, so look at next line
JU3B:	TRNN F,NEG!REL		;Is this a JFILL or a last line of par.
	SOSG JSCNT		;Do not count final word ending
	JRST JU3A		;Line must be left un-justified
;  Prepare for justification
	MOVE T,JSIZE
	SUB T,JWCOL
	LSH T,3			;Multiply by 8
	MOVEM T,JSINC
	MOVN G,JSIZE
	SETZM JSIZE		;Used in the JUSPAD routine for accumulated JSINC
	SETZM JWPT		;Used in JUSPAD for accumulated insertions
	SKIPA
JU3D:	MOVN G,JWCOL		;Un-justified case
	HRLZS G
	PUSHJ P,J2PASS		;Set-up fpr the second pass

;   Main character transfering loop
JU4:	ILDB C,A
	TDNE H,JCTAB(C)
	XCT @JCTAB(C)		;Caution, return may be to .-2, ., or .+1
LEG	IDPB C,D
	AOBJN G,JU4

	PUSHJ P,JUFIX		;Fix up line just finished
	MOVE T,JCNTC
	MOVEM T,JCNT
	SETZM JPASSF		;Get set for new first pass
	TRNN F,REL		;Is it to be a new par?
	JRST JU6		;No, so go on
	SKIPN Q,BNUM		;Will blank lines be needed?
	JRST JU5A		;No
;  Introduce needed blank lines
JU5:	PUSHJ P,JMORE		;Get space for it
	AOS TT,TXTNUM
LEG	HRRM TT,TXTSER(I)
LEG	HRRZS TXTFLG(I)		;Zero flg portion
	SETZ G,
	MOVE D,I
	ADD D,[440700,,LLDESC]
	MOVEI C,40
	IDPB C,D
	PUSHJ P,JUFIX		;Finish off this line
	SOJG Q,JU5

;  Eat any old blank lines
JU5A:	PUSHJ P,NEXTLI
	SOJG JCNT
	JRST JU7
	HRRZ T,TXTCNT(B)
	JUMPE T,JU5A
	PUSHJ P,JMORE		;Get space for new line
	JRST JU1D

;It is safe to go on
;  But, a new input line may be needed
JU6:	MOVE T,A
JU6A:	ILDB C,T
	CAIE C,40
	CAIN C,11
	JRST JU6A		;Eat all spaces and TABs
	CAIE C,15
	JRST JU6C		;It's OK
JU6B:	PUSHJ P,NEXTLI
	SOSG JCNT
	JRST JU7		;WOOPS! we are through
JU6C:	PUSHJ P,JMORE		;Get space for it
	JRST JU1D

;Complete the links to the following text
JU7:	MOVE T,JLPT		;Now fix new right link
	HRRM B,(T)		;A references  next line
	HRLM T,(B)		;And backward link to the new line
	PUSHJ P,ENDFIX
	TRO F,WRITE!DSPALL
	TLZ F,NOCHK
	JRST JEXIT(E)

;It should be safe to FSGIVE now, count is in Q
;	MOVE A,JPTR		;Get back address of first old line
;	JUMPE Q,.+4
;	PUSHJ P,FSGIVE		;And give up its space
;	HRRZ A,(A)
;	SOJG Q,.-2		;Do this for all the old lines
;INDENT INDMAR CENTER

INDENT:	TRO F,NEG		;To prevent padding
	TRNN F,ATTMOD
	JRST INDEN1
	TRNN F,ARG
	MOVEI A,-1		;Do entire ATTACH buffer
	SKIPA
INDEN1:	TRO F,ARG		;Default value is 1 if not in ATTACH
	PUSHJ P,INDMAR		;Initialize and get typed-in margins
	MOVSI H,JALL		;Set to dispatch on all characters
	MOVEI DSP,J1DSP		;Set dispatch for new output line
	SETOM PARFLG		;To force a new line on each CR
	MOVE B,JPTR


;  To read in a single margin specification returning value in A
;  7777 means do not change. Uses A, C and T registers.
INDMAR:	MOVE T,EXTPNT		;To read margin changing instructions.
	MOVEM T,TYIPNT		;Set pointer.
	HRLI C,(<MOVEI C,>)
	MOVEM C,TYIINS
	SETZ T,
	MOVEI A,7777		;This means use default value
INDMA2:	PUSHJ P,TYI		;Get first character if any.
	POPJ P,			;We are to use default values.
	CAIN C," "
	JRST INDMA2		;Ignore an extra space in here.
	CAIN C,"+"
	JRST INDMA2		;Ignore a + sign
	CAIN C,"-"
	SOJA T,INDMA2
	SETZ A,
INDMA3:	CAIG C,71
	CAIGE C,60
	JRST INDMA4
	IMULI A,12
	ADDI A,-"0"(C)
	CAILE A,EDCHRL		;Allow only 126 display char. because of line buffer
	MOVEI A,EDCHRL
	PUSHJ P,TYI
	JRST INDMA4		;We can only have one number anyway.
	JRST INDMA3
INDMA4:	SKIPE T
	MOVNS A
	POPJ P,

LFARR:
RFARR:
JLEFT:
ALINE:
ALIGN:

CENTER:	TRO F,NEG		;To prevent padding
	TRNN F,ATTMOD
	JRST CENT1
	TRNN F,ARG
	MOVEI A,-1		;Do entire ATTACH buffer
	SKIPA
CENT1:	TRO F,ARG		;Default value is 1 if not in ATTACH
	PUSHJ P,JGINIT		;Initialize and get typed-in margins
	MOVSI H,JALL		;Set to dispatch on all characters
	MOVEI DSP,J1DSP		;Set dispatch for new output line
	SETOM PARFLG		;To force a new line on each CR
	MOVE T,RMAR
	SUB T,LMAR
	MOVEM T,JSIZE		;Use for centering
	MOVE B,JPTR
CENT2:	HRRZ C,TXTCNT(B)	;Is this line blank?
	JUMPN C,CENT3		;No
	HRRZ B,(B)		;Skip over it
	MOVEM B,JPTR
	SOSG JCNT		;One less line to process
	JRST CENT2
	POPJ P,			;No data

CENT3:	PUSHJ P,JNEW		;Get space for new lines and fix flags etc.
CENT3A:	MOVE A,B
	ADD A,[440700,,LLDESC]
	MOVSI G,-1		;Only limit on line size

CENT4:	ILDB C,A
	TDNE H,JCTAB(C)
	XCT @JCTAB(C)
	AOBJN G,CENT4

	MOVE T,JSIZE
	SUB T,JWCOL
	SKIPGE T
	MOVEI T,0
	LSH T,-1		;Divide by 2
	MOVEM T,JMARG		;Set new margin
	MOVN G,JWCOL
	HRLZS G
	PUSHJ P,J2PASS		;This will work here

CENT5:	ILDB C,A
	TDNE H,JCTAB(C)
	XCT @JCTAB(C)
	IDPB C,D
	AOBJN G,CENT5
	PUSHJ P,JUFIX

CENT6:	PUSHJ P,NEXTLI
	SOJG JCNT
	JRST CENT8
	HRRZ T,TXTCNT(B)
	JUMPN T,CENT7
	AOS TT,TXTNUM
LEG	HRRM TT,TXTSER(I)
LEG	HRRZS TXTFLG(I)		;Zero flg portion
	SETZ G,
	MOVE D,I
	ADD D,[440700,,LLDESC]
	MOVEI C,40
	IDPB C,D
	PUSHJ P,JUFIX		;Finish off this line
	JRST CENT6

CENT7:	PUSHJ P,JMORE
	JRST CENT3A

CENT8:	JRST JU7